﻿using System;
using System.Collections.Generic;
using System.Text;
using AdaptiveAgents.Loggers;

namespace AdaptiveAgents
{
    /// <summary>
    /// A class that saves a set of observations on a particular game
    /// </summary>
    public class ObservationsSet
    {
        //set of observation
        public List<Observation> observations = new List<Observation>();

        /// <summary>
        /// Add an observation to the observation set
        /// </summary>
        /// <param name="observation">Observation to add</param>
        public void addObservation(Observation observation) { observations.Add(observation); }
        
        /// <summary>
        /// Sets the next agent of the most recently added observation
        /// </summary>
        /// <param name="ag">The agent playing this round</param>
        public void updateNextAgent(int ag)
        {  
            observations[observations.Count - 1].NextAgent = ag;
        }

        /// <summary>
        /// Get the size of the observation set
        /// </summary>
        /// <returns>The size of the observation set</returns>
        public int getSize() { return observations.Count; }

        /// <summary>
        /// Get a specific observation
        /// </summary>
        /// <param name="index">Index of the observation</param>
        /// <returns>The observation according to the index</returns>
        public Observation get(int index) { return observations[index]; }

        /// <summary>
        /// Create an observation set with all the plays of a specific agent
        /// </summary>
        /// <param name="id">The ID of the agent</param>
        /// <returns>An ObservationsSet containing all the observations of an agent with "id" ID</returns>
        public ObservationsSet getObservationsByAgentID(int id)
        {
            return getObservationsByAgentID(id, int.MaxValue);
        }

        /// <summary>
        /// Create an observation set with the last "maxMemory" plays of a specific agent
        /// </summary>
        /// <param name="id">The ID of the agent</param>
        /// <param name="maxMemory">max plays of the agent in the returning observation set</param>
        /// <returns>An ObservationsSet containing the last "maxMemory" observations of an agent with "id" ID</returns>
        public ObservationsSet getObservationsByAgentID(int id, int maxMemory)
        {
            //create new observation set
            ObservationsSet observationSet = new ObservationsSet();
            //enter all the observations of the wanted agent 
            foreach (Observation observation in observations)
                if (observation.ID == id) observationSet.addObservation(observation);
            
            if (maxMemory < observationSet.getSize()) //if the agent had more plays then the memory we want...
            {
                //create new observation set
                ObservationsSet trimmedObservationSet = new ObservationsSet();
                //enter all "maxMemory" last plays of that agent
                for (int index = 0; index < maxMemory; index++)
                {
                    trimmedObservationSet.addObservation(observationSet.get(observationSet.getSize() -
                                                (maxMemory - index)));
                }
                //print to loggers
                AdaptiveAgents.logger.WriteLine(MessageType.HackMessage,"Trimming to last {0} observations:", maxMemory);
                trimmedObservationSet.printObservations(2, 2000);
                return trimmedObservationSet;
            }

            return observationSet;
        }

        /// <summary>
        /// Print to loggers
        /// </summary>
        /// <param name="media">Media ID</param>
        /// <param name="logLevel">Log level</param>
        public void printObservations(int media, int logLevel)
        {
            foreach (Observation observation in observations)
                AdaptiveAgents.logger.WriteLine(MessageType.ObservationPrint,
                    observation.Time, observation.ID,
                    observation.Value, observation.NextAgent);               
        }

    }

}
